/*
 * DAC_CAL.c
 *
 * Created: 8/17/2013 5:20:41 PM
 *  Author: Tim
 */ 


#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <math.h>
#include <avr/eeprom.h>

#include "board/board.h"
#include "adc.h"

#define calDataWords	256

int16_t adcCalData0[calDataWords];
int16_t adcCalData1[calDataWords];
int16_t adcCalData2[calDataWords];
int16_t adcCalData3[calDataWords];

adcCal[4];

volatile uint16_t increment;
volatile uint8_t eepromAddress = 0;


int main(void)
{
	brdInit();
	PORTC.DIRSET = 1;
	//create overflow interrupt
	TCC0.CTRLA = TC_CLKSEL_DIV1_gc;
	TCC0.PER = 32000-1;
	TCC0.INTCTRLA = TC_OVFINTLVL_MED_gc;
	TCC0.CNT = 0;
	
	ADCA.CH0.INTCTRL = ADC_CH_INTLVL_LO_gc;
	ADCA.CH1.INTCTRL = ADC_CH_INTLVL_LO_gc;
	ADCA.CH2.INTCTRL = ADC_CH_INTLVL_LO_gc;
	ADCA.CH3.INTCTRL = ADC_CH_INTLVL_LO_gc;
	PMIC.CTRL |= PMIC_MEDLVLEN_bm |PMIC_LOLVLEN_bm;
	sei();
	
    while(1)
    {
		
		while(TCC0.INTCTRLA & TC_OVFINTLVL_MED_gc);
			ADCA.CH0.CTRL	 = ADC_CH_GAIN_4X_gc | ADC_CH_INPUTMODE_DIFFWGAIN_gc;
			ADCA.CH1.CTRL	 = ADC_CH_GAIN_4X_gc | ADC_CH_INPUTMODE_DIFFWGAIN_gc;
			ADCA.CH2.CTRL	 = ADC_CH_GAIN_4X_gc | ADC_CH_INPUTMODE_DIFFWGAIN_gc;
			ADCA.CH3.CTRL	 = ADC_CH_GAIN_4X_gc | ADC_CH_INPUTMODE_DIFFWGAIN_gc;
			increment=0;
			TCC0.INTCTRLA = TC_OVFINTLVL_MED_gc;
		
		while(TCC0.INTCTRLA & TC_OVFINTLVL_MED_gc);
			ADCA.CH0.CTRL	 = ADC_CH_GAIN_8X_gc | ADC_CH_INPUTMODE_DIFFWGAIN_gc;
			ADCA.CH1.CTRL	 = ADC_CH_GAIN_8X_gc | ADC_CH_INPUTMODE_DIFFWGAIN_gc;
			ADCA.CH2.CTRL	 = ADC_CH_GAIN_8X_gc | ADC_CH_INPUTMODE_DIFFWGAIN_gc;
			ADCA.CH3.CTRL	 = ADC_CH_GAIN_8X_gc | ADC_CH_INPUTMODE_DIFFWGAIN_gc;
			increment=0;
			TCC0.INTCTRLA = TC_OVFINTLVL_MED_gc;
		
		while(TCC0.INTCTRLA & TC_OVFINTLVL_MED_gc);
			ADCA.CH0.CTRL	 = ADC_CH_GAIN_16X_gc | ADC_CH_INPUTMODE_DIFFWGAIN_gc;
			ADCA.CH1.CTRL	 = ADC_CH_GAIN_16X_gc | ADC_CH_INPUTMODE_DIFFWGAIN_gc;
			ADCA.CH2.CTRL	 = ADC_CH_GAIN_16X_gc | ADC_CH_INPUTMODE_DIFFWGAIN_gc;
			ADCA.CH3.CTRL	 = ADC_CH_GAIN_16X_gc | ADC_CH_INPUTMODE_DIFFWGAIN_gc;
			increment=0;
			TCC0.INTCTRLA = TC_OVFINTLVL_MED_gc;
		
		while(TCC0.INTCTRLA & TC_OVFINTLVL_MED_gc);
			ADCA.CH0.CTRL	 = ADC_CH_GAIN_32X_gc | ADC_CH_INPUTMODE_DIFFWGAIN_gc;
			ADCA.CH1.CTRL	 = ADC_CH_GAIN_32X_gc | ADC_CH_INPUTMODE_DIFFWGAIN_gc;
			ADCA.CH2.CTRL	 = ADC_CH_GAIN_32X_gc | ADC_CH_INPUTMODE_DIFFWGAIN_gc;
			ADCA.CH3.CTRL	 = ADC_CH_GAIN_32X_gc | ADC_CH_INPUTMODE_DIFFWGAIN_gc;
			increment=0;
			TCC0.INTCTRLA = TC_OVFINTLVL_MED_gc;
		
		while(TCC0.INTCTRLA & TC_OVFINTLVL_MED_gc);
			ADCA.CH0.CTRL	 = ADC_CH_GAIN_64X_gc | ADC_CH_INPUTMODE_DIFFWGAIN_gc;
			ADCA.CH1.CTRL	 = ADC_CH_GAIN_64X_gc | ADC_CH_INPUTMODE_DIFFWGAIN_gc;
			ADCA.CH2.CTRL	 = ADC_CH_GAIN_64X_gc | ADC_CH_INPUTMODE_DIFFWGAIN_gc;
			ADCA.CH3.CTRL	 = ADC_CH_GAIN_64X_gc | ADC_CH_INPUTMODE_DIFFWGAIN_gc;
			increment=0;
			TCC0.INTCTRLA = TC_OVFINTLVL_MED_gc;
		while(TCC0.INTCTRLA & TC_OVFINTLVL_MED_gc);
		cli();
		while(1)
		{
			_delay_ms(100);
			PORTC.OUTTGL = 1;
		}	
		
    }
}

ISR(TCC0_OVF_vect)
{
	if(increment>=10){
	adcCalData0[increment-10] = -filterData(&adcCh0_data);
	adcCalData1[increment-10] = -filterData(&adcCh1_data);
	adcCalData2[increment-10] = -filterData(&adcCh2_data);
	adcCalData3[increment-10] = -filterData(&adcCh3_data);
	}
	//if all data is stored stop the interrupt
	if(increment++ == calDataWords+10) 
	{
		TCC0.INTCTRLA = TC_OVFINTLVL_OFF_gc;	
	
		volatile int32_t temp;
		uint16_t j;
	
		temp = 0;
		for(j=0;j<calDataWords;j++)
		{
			temp += adcCalData0[j];
		}
	
		adcCal[0] = round(temp/256.0);
	
		temp = 0;
		for(j=0;j<calDataWords;j++)
		{
			temp += adcCalData1[j];
		}
	
		adcCal[1] = round(temp/256.0);
	
		temp = 0;
		for(j=0;j<calDataWords;j++)
		{
			temp += adcCalData2[j];
		}
	
		adcCal[2] = round(temp/256.0);
	
		temp = 0;
		for(j=0;j<calDataWords;j++)
		{
			temp += adcCalData3[j];
		}
	
		adcCal[3] = round(temp/256.0);
		asm("nop");
		eeprom_write_word(eepromAddress,adcCal[0]);
		eepromAddress+=2;
		eeprom_write_word(eepromAddress,adcCal[1]);
		eepromAddress+=2;
		eeprom_write_word(eepromAddress,adcCal[2]);
		eepromAddress+=2;
		eeprom_write_word(eepromAddress,adcCal[3]);
		eepromAddress+=2;
		asm("nop");
		
	}
	
}